package per.hnvcam.searchext.data.dao.impl;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import per.hnvcam.searchext.data.dao.WordCountDAO;
import per.hnvcam.searchext.data.model.WebReference;
import per.hnvcam.searchext.data.model.Word;
import per.hnvcam.searchext.data.model.WordCount;
import per.hnvcam.searchext.text.WordCounter;

import java.util.List;

@Service("WordCountDAO")
@Transactional
public class WordCountDAOImpl extends BaseDAOImpl implements WordCountDAO {

   @Autowired
   @Qualifier("sessionFactory")
   private SessionFactory sessionFactory;

   @SuppressWarnings("unchecked")
   @Override
   public List<WordCount> listWordCounts() {
      return getHibernateTemplate().find("from WordCount");
   }

   @Override
   public void saveOrUpdate(WordCount wordCount) {
      getHibernateTemplate().saveOrUpdate(wordCount);
   }

   @Override
   public void save(WordCount wordCount) {
      getHibernateTemplate().save(wordCount);
   }

   @Override
   public WordCount findByWebReferenceAndWord(WebReference webReference, Word word) {
      return findByWebReferenceIdAndWordId(webReference.getId(), word.getId());
   }

   @Override
   public WordCount findByWebReferenceIdAndWordId(long webReferenceId, long wordId) {
      @SuppressWarnings("rawtypes")
      List result = getHibernateTemplate().find("from WordCount wc where" +
         "wc.webReference.id = ? and wc.word.id = ?", webReferenceId, wordId);
      if (result != null && result.size() > 0) {
         return (WordCount) result.get(0);
      }
      return null;
   }

   @Override
   public List<WordCount> findByWebReference(WebReference webReference) {
      return findByWebReferenceId(webReference.getId());
   }

   @SuppressWarnings("unchecked")
   @Override
   public List<WordCount> findByWebReferenceId(long webReferenceId) {
      return getHibernateTemplate().find("from WordCount wc where wc.webReference.id = ?", webReferenceId);
   }

   @SuppressWarnings("unchecked")
   @Override
   public List<WordCount> findByWordId(long wordId) {
      return getHibernateTemplate().find("from WordCount wc where wc.word.id = ?", wordId);
   }

   @Override
   public List<WordCount> findByWord(Word word) {
      return findByWordId(word.getId());
   }

   @Override
   public void bulkSave(WordCounter wordCounter, WebReference webReference, int wordCountMinimum) {
      Session session = sessionFactory.openSession();
      Transaction tx = null;
      try {
         tx = session.beginTransaction();
         for (String word : wordCounter) {
            if (wordCounter.resultOf(word) < wordCountMinimum) {
               continue;
            }
            Word w = null;
            Query query = session.createQuery("select w from Word as w where w.label = :word");
            query.setString("word", word);
            @SuppressWarnings("rawtypes")
            List result = query.list();
            if (result != null && result.size() > 0) {
               w = (Word) result.get(0);
               if (w.getMaxCount() < wordCounter.resultOf(word)) {
                  w.setMaxCount(wordCounter.resultOf(word));
                  session.update(w);
               }
            } else {
               w = new Word();
               w.setLabel(word);
               w.setMaxCount(wordCounter.resultOf(word));
               session.save(w);
            }
            WordCount wCount = new WordCount();
            wCount.setWord(w);
            wCount.setWebReference(webReference);
            wCount.setCount(wordCounter.resultOf(word));
            session.save(wCount);

         }
         tx.commit();
      }
      catch (Exception e) {
         if (tx != null) {
            tx.rollback();
         }
      }
      finally {
         session.close();
      }
   }
}
